﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using System.Net.Http.Headers;

namespace M.Web
{
	/// <summary>
	/// 简单制作的调用WebApi的工具
	/// </summary>
	public class WebApiClient : IDisposable
	{
		/// <summary>
		/// 通过指定一个WebApi基础地址来初始化Client实例
		/// </summary>
		/// <param name="webApiBaseUrl"></param>
		public WebApiClient(string webApiBaseUrl)
		{
			MValidator.CheckForEmptyString("Web Api Base Url", webApiBaseUrl);
			this.Client = new HttpClient();
			this.Client.BaseAddress = new Uri(webApiBaseUrl);
			this.Client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
			this.Client.DefaultRequestHeaders.AcceptCharset.Add(new StringWithQualityHeaderValue("utf-8"));
		}
		#region Get

		/// <summary>
		/// 同步获取结果
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="webApi"></param>
		/// <returns></returns>
		public T GetSync<T>(string webApi)
		{
			using (HttpResponseMessage response = this.Client.GetAsync(webApi).Result)
			{
				ThrowResponseException(response);
				return response.Content.ReadAsAsync<T>().Result;
			}
		}

		#endregion

		#region Post
		/// <summary>
		/// 同步提交Post请求，请求正文使用DataContractJsonSerializer进行JSON序列化
		/// </summary>
		/// <typeparam name="TResult">返回值类型</typeparam>
		/// <typeparam name="TObject">参数值类型用于序列化请求正文</typeparam>
		/// <param name="webApi">WebApi相对地址</param>
		/// <param name="obj">请求参数</param>
		/// <returns></returns>
		public TResult PostAsDCJsonSync<TResult, TObject>(string webApi, TObject obj)
		{
			using (HttpContent content = new StringContent(MFormatter.ToDCJson<TObject>(obj)))
			{
				content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
				using (HttpResponseMessage response = this.Client.PostAsync(webApi, content).Result)
				{
					ThrowResponseException(response);
					return response.Content.ReadAsAsync<TResult>().Result;
				}
			}
		}
		/// <summary>
		/// 同步提交Post请求，使用NewstonJSON进行JSON序列化
		/// </summary>
		/// <typeparam name="TResult">返回值类型</typeparam>
		/// <param name="webApi">WebApi相对地址</param>
		/// <param name="obj">请求参数</param>
		/// <returns></returns>
		public TResult PostAsJsonSync<TResult>(string webApi, object obj)
		{
			using (HttpResponseMessage response = this.Client.PostAsJsonAsync(webApi, obj).Result)
			{
				ThrowResponseException(response);
				return response.Content.ReadAsAsync<TResult>().Result;
			}
		}

		#endregion

		#region Put

		/// <summary>
		/// 同步提交Put请求，请求正文使用DataContractJsonSerializer进行JSON序列化
		/// </summary>
		/// <typeparam name="TResult">返回值类型</typeparam>
		/// <typeparam name="TObject">参数值类型用于序列化请求正文</typeparam>
		/// <param name="webApi">WebApi相对地址</param>
		/// <param name="obj">请求参数</param>
		/// <returns></returns>
		public TResult PutAsDCJsonSync<TResult, TObject>(string webApi, TObject obj)
		{
			using (HttpContent content = new StringContent(MFormatter.ToDCJson<TObject>(obj)))
			{
				content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
				using (HttpResponseMessage response = this.Client.PutAsync(webApi, content).Result)
				{
					ThrowResponseException(response);
					return response.Content.ReadAsAsync<TResult>().Result;
				}
			}
		}

		/// <summary>
		/// 同步提交Put请求，使用NewstonJSON进行JSON序列化
		/// </summary>
		/// <typeparam name="TResult">返回值类型</typeparam>
		/// <param name="webApi">WebApi相对地址</param>
		/// <param name="obj">请求参数</param>
		/// <returns></returns>
		public TResult PutAsJsonSync<TResult>(string webApi, object obj)
		{
			using (HttpResponseMessage response = this.Client.PutAsJsonAsync(webApi, obj).Result)
			{
				ThrowResponseException(response);
				return response.Content.ReadAsAsync<TResult>().Result;
			}
		}

		#endregion

		#region Delete
		/// <summary>
		/// 同步提交Post请求
		/// </summary>
		/// <param name="webApi"></param>
		/// <returns></returns>
		public void DeleteSync(string webApi)
		{
			using (HttpResponseMessage response = this.Client.DeleteAsync(webApi).Result)
			{
				ThrowResponseException(response);
			}
		}
		#endregion

		/// <summary>
		/// 添加请求头
		/// </summary>
		/// <param name="name"></param>
		/// <param name="value"></param>
		public void AddHeader(string name, string value)
		{
			MValidator.CheckForEmptyString("Web Api Request Header Name", name);
			MValidator.CheckForEmptyString("Web Api Request Header Value", value);
			this.Client.DefaultRequestHeaders.Add(name, value);
		}
		/// <summary>
		/// 通用的抛出响应流中的异常
		/// </summary>
		/// <param name="response"></param>
		protected void ThrowResponseException(HttpResponseMessage response)
		{
			if (!response.IsSuccessStatusCode)
				throw new M.MException(System.Web.HttpContext.Current.Server.UrlDecode(response.ReasonPhrase), MExceptionLevel.Stop, new Exception(response.Content.ToString()));
		}

		/// <summary>
		/// HttpClient实例
		/// </summary>
		protected HttpClient Client = null;

		#region IDispose
		/// <summary>
		/// 释放资源
		/// </summary>
		public void Dispose()
		{
			this.Dispose(true);
			GC.SuppressFinalize(this);
		}
		/// <summary>
		/// 释放资源
		/// </summary>
		/// <param name="disposing"></param>
		protected virtual void Dispose(bool disposing)
		{
			if (disposing)
			{
				if (Client != null)
				{
					Client.Dispose();
				}
			}
		}
		#endregion
	}
}
